#ifndef EXECUTOR_H
#define EXECUTOR_H

#include "../../include/gudb.h"
#include "../planner/query_planner.h"
#include "../storage/storage_engine.h"
#include "../memory/memory_manager.h"
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>

// Forward declaration for storage iterator (until storage layer is fully implemented)
typedef void storage_iterator_t;

// Forward declarations
typedef struct executor_context executor_context_t;
typedef struct tuple tuple_t;
typedef struct tuple_slot tuple_slot_t;
typedef struct executor_state executor_state_t;

// Data types for values
typedef enum {
    VALUE_NULL = 0,
    VALUE_BOOL,
    VALUE_INT32,
    VALUE_INT64,
    VALUE_FLOAT,
    VALUE_DOUBLE,
    VALUE_STRING,
    VALUE_BLOB,
    VALUE_TIMESTAMP
} value_type_t;

// Value structure for storing data
typedef struct {
    value_type_t type;
    bool is_null;
    union {
        bool bool_val;
        int32_t int32_val;
        int64_t int64_val;
        float float_val;
        double double_val;
        struct {
            char* data;
            uint32_t length;
        } string_val;
        struct {
            void* data;
            uint32_t length;
        } blob_val;
        uint64_t timestamp_val;
    } data;
} value_t;

// Tuple slot - represents a single row with column values
struct tuple_slot {
    value_t* values;        // Array of column values
    uint32_t column_count;  // Number of columns
    bool* is_null;          // Null indicators
    uint32_t ref_count;     // Reference counting for memory management
};

// Tuple - wrapper around tuple slot with metadata
struct tuple {
    tuple_slot_t* slot;     // Actual data
    uint32_t tuple_id;      // Unique identifier
    void* table_oid;        // Table object ID (for updates/deletes)
    bool is_heap_tuple;     // Whether tuple comes from heap or index
};

// Execution result status
typedef enum {
    EXEC_SUCCESS = 0,       // Operation successful
    EXEC_EOF,               // End of result set
    EXEC_ERROR,             // Error occurred
    EXEC_QUAL_FALSE,        // Qualification failed (for filters)
    EXEC_RESCAN             // Rescan requested
} exec_result_t;

// Executor node state (base class for all operators)
struct executor_state {
    plan_node_t* plan;              // Associated plan node
    executor_context_t* context;    // Execution context
    
    // Volcano iterator interface
    exec_result_t (*open)(struct executor_state* state);
    exec_result_t (*next)(struct executor_state* state, tuple_t** tuple);
    void (*close)(struct executor_state* state);
    void (*rescan)(struct executor_state* state);
    
    // State management
    bool is_open;
    bool needs_rescan;
    uint64_t tuples_processed;
    uint64_t tuples_returned;
    
    // Child executors (for tree structure)
    struct executor_state** children;
    uint32_t child_count;
    
    // Operator-specific state data
    void* private_state;
};

// Execution context - contains global execution state
struct executor_context {
    // Database connection
    gudb* db;
    gudb_txn* transaction;
    
    // Memory management
    memory_manager_t* memory_manager;
    
    // Statistics
    uint64_t total_tuples_processed;
    uint64_t total_pages_read;
    uint64_t total_pages_written;
    uint64_t execution_time_us;
    
    // Configuration
    uint32_t work_mem_kb;           // Working memory limit in KB
    uint32_t temp_buffers;          // Number of temp buffers
    bool enable_hashjoin;           // Enable hash joins
    bool enable_mergejoin;          // Enable merge joins
    bool enable_nestloop;           // Enable nested loop joins
    
    // Error handling
    char* error_message;
    int error_code;
    
    // Tuple format descriptor cache
    void* tuple_desc_cache;
    
    // Parameter values (for prepared statements and correlated subqueries)
    value_t* parameters;
    uint32_t parameter_count;
    
    // Correlation context (for correlated subqueries)
    value_t* correlation_values;
    uint32_t correlation_count;
    char** correlation_names;
};

// Specific executor state structures

// Scan executor state
typedef struct {
    storage_iterator_t* iterator;   // Storage layer iterator
    expression_t* filter;           // WHERE clause filter
    char* table_name;
    uint64_t scanned_tuples;
    uint64_t filtered_tuples;
} scan_executor_state_t;

// Index scan executor state
typedef struct {
    storage_iterator_t* iterator;   // Index iterator
    expression_t* index_condition;  // Index search condition
    expression_t* filter;           // Additional filter
    char* table_name;
    char* index_name;
    bool is_unique_scan;
    uint64_t scanned_tuples;
} index_scan_executor_state_t;

// Filter executor state
typedef struct {
    executor_state_t* child;        // Child executor
    expression_t* condition;        // Filter condition
    uint64_t filtered_tuples;
} filter_executor_state_t;

// Project executor state
typedef struct {
    executor_state_t* child;        // Child executor
    expression_t** expressions;     // Projection expressions
    char** column_names;            // Output column names
    uint32_t expr_count;
    tuple_slot_t* result_slot;      // Reusable result slot
} project_executor_state_t;

// Join executor state (base)
typedef struct {
    executor_state_t* left_child;   // Left input
    executor_state_t* right_child;  // Right input
    join_type_t join_type;
    expression_t* join_condition;
    uint64_t joined_tuples;
    tuple_slot_t* result_slot;      // Reusable result slot
} join_executor_state_t;

// Nested loop join specific state
typedef struct {
    join_executor_state_t base;
    tuple_t* current_outer_tuple;   // Current outer tuple
    bool need_new_outer;            // Need to fetch new outer tuple
    uint64_t inner_scans;           // Number of inner scans
} nested_loop_join_state_t;

// Hash join specific state
typedef struct {
    join_executor_state_t base;
    void* hash_table;               // Hash table for inner relation
    bool hash_table_built;          // Whether hash table is built
    void* hash_iterator;            // Current hash table iterator
    tuple_t* current_outer_tuple;   // Current outer tuple being probed
    uint32_t hash_bucket_count;
    uint64_t hash_collisions;
} hash_join_state_t;

// Sort executor state
typedef struct {
    executor_state_t* child;        // Child executor
    expression_t** sort_keys;       // Sort key expressions
    bool* ascending;                // Sort directions
    uint32_t key_count;
    
    // Sorting state
    tuple_t** tuples;               // Array of tuples to sort
    uint32_t tuple_count;
    uint32_t tuple_capacity;
    uint32_t current_index;         // Current output position
    bool tuples_sorted;             // Whether sorting is complete
    
    // External sorting (for large datasets)
    bool use_external_sort;
    char** temp_files;
    uint32_t temp_file_count;
} sort_executor_state_t;

// Aggregation executor state
typedef struct {
    executor_state_t* child;        // Child executor
    expression_t** group_by;        // GROUP BY expressions
    expression_t** aggregates;      // Aggregate expressions
    uint32_t group_count;
    uint32_t agg_count;
    
    // Aggregation state
    void* hash_table;               // Hash table for grouping
    bool aggregation_done;          // Whether aggregation is complete
    void* agg_iterator;             // Iterator over aggregation results
    uint64_t groups_processed;
} aggregate_executor_state_t;

// Limit executor state
typedef struct {
    executor_state_t* child;        // Child executor
    uint64_t limit;                 // Maximum tuples to return
    uint64_t offset;                // Tuples to skip
    uint64_t returned_tuples;       // Tuples returned so far
    uint64_t skipped_tuples;        // Tuples skipped so far
} limit_executor_state_t;

// Main executor API
executor_context_t* executor_create_context(gudb* db, gudb_txn* txn, memory_manager_t* mm);
void executor_destroy_context(executor_context_t* context);

// Executor tree creation
executor_state_t* executor_create_tree(executor_context_t* context, plan_node_t* plan);
void executor_destroy_tree(executor_state_t* executor);

// Execution control
exec_result_t executor_open(executor_state_t* executor);
exec_result_t executor_next(executor_state_t* executor, tuple_t** tuple);
void executor_close(executor_state_t* executor);
void executor_rescan(executor_state_t* executor);

// High-level execution functions
exec_result_t executor_run_query(executor_context_t* context, plan_node_t* plan, 
                                tuple_t*** results, uint32_t* result_count);
exec_result_t executor_run_dml(executor_context_t* context, plan_node_t* plan, 
                              uint64_t* affected_rows);

// Tuple management
tuple_t* tuple_create(uint32_t column_count);
tuple_t* tuple_copy(tuple_t* source);
void tuple_destroy(tuple_t* tuple);
tuple_slot_t* tuple_slot_create(uint32_t column_count);
void tuple_slot_destroy(tuple_slot_t* slot);

// Value management
value_t value_make_null(void);
value_t value_make_bool(bool val);
value_t value_make_int32(int32_t val);
value_t value_make_int64(int64_t val);
value_t value_make_float(float val);
value_t value_make_double(double val);
value_t value_make_string(const char* str);
value_t value_copy(const value_t* source);
void value_destroy(value_t* value);
bool value_equals(const value_t* a, const value_t* b);
int value_compare(const value_t* a, const value_t* b);

// Expression evaluation
exec_result_t evaluate_expression(expression_t* expr, tuple_t* tuple, 
                                 executor_context_t* context, value_t* result);
bool evaluate_qualification(expression_t* qual, tuple_t* tuple, 
                           executor_context_t* context);

// Expression evaluation helpers
exec_result_t evaluate_binary_operation(token_type_t operator, const value_t* left_val, 
                                       const value_t* right_val, value_t* result);
exec_result_t evaluate_unary_operation(token_type_t operator, const value_t* operand_val, 
                                      value_t* result);
exec_result_t evaluate_function_call(expression_t* expr, tuple_t* tuple, 
                                    executor_context_t* context, value_t* result);

// Utility functions
const char* exec_result_to_string(exec_result_t result);
const char* value_type_to_string(value_type_t type);
void executor_print_stats(executor_context_t* context);

// Join utility functions
tuple_t* join_tuples(tuple_t* left, tuple_t* right, join_type_t join_type);
bool join_condition_matches(tuple_t* left, tuple_t* right, expression_t* condition,
                           executor_context_t* context);

// Hash table utilities (for hash joins and aggregation)
void* hash_table_create(uint32_t bucket_count);
void hash_table_destroy(void* hash_table);
int hash_table_insert(void* hash_table, tuple_t* tuple, uint32_t hash_value);
tuple_t** hash_table_lookup(void* hash_table, uint32_t hash_value, uint32_t* count);
uint32_t hash_tuple(tuple_t* tuple, expression_t** keys, uint32_t key_count);

// Sorting utilities
int tuple_compare(const void* a, const void* b, void* context);
void sort_tuples(tuple_t** tuples, uint32_t count, expression_t** sort_keys,
                bool* ascending, uint32_t key_count);

// Correlated subquery support
void executor_set_correlation_value(executor_context_t* context, const char* column_name, const value_t* value);
void executor_clear_correlation_values(executor_context_t* context);

// Error handling
void executor_set_error(executor_context_t* context, int error_code, const char* message);
bool executor_has_error(executor_context_t* context);
const char* executor_get_error_message(executor_context_t* context);

#endif // EXECUTOR_H